package com.zmm.util.component;

import com.zmm.common.annotation.SysLog;
import com.zmm.common.log.ReqRspLog;
import com.zmm.util.time.DateUtil;
import lombok.extern.slf4j.Slf4j;
import net.logstash.logback.marker.Markers;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * @author 900045
 * @description:
 * @name WebLogAspect
 * @date By 2021-08-13 14:45:47
 */
@Aspect
@Component
@Order(1)
@Slf4j
@Configuration
public class WebLogAspect {

	@Resource
	private MongoTemplate mongoTemplate;

	/**
	 * 开始时间
	 */
	private  Long START_TIME;

	@Pointcut("@annotation(com.zmm.common.annotation.SysLog)")
	public void webLog() {

	}

	@Before("webLog()")
	public void doBefore(JoinPoint joinPoint) {
		Method method = common(joinPoint);
		if (method.isAnnotationPresent(SysLog.class)) {
			SysLog annotation = method.getAnnotation(SysLog.class);
			START_TIME = DateUtil.getNowTime();
			log.info("[{}] 方法开始执行...[{}]",annotation.location(),START_TIME);
		}
	}


	@AfterReturning(value = "webLog()", returning = "joinPoint")
	public void doAfterReturning(JoinPoint joinPoint) {
		Method method = common(joinPoint);
		if (method.isAnnotationPresent(SysLog.class)) {
			SysLog annotation = method.getAnnotation(SysLog.class);
			log.info("[{}] 方法执行结束...[{}]",annotation.location(),DateUtil.getNowTime()- START_TIME);
		}
	}
	
	/**
	 * 通用方法
	 * @author: 900045
	 * @date: 2021-08-13 15:24:38
	 * @throws 
	 * @param joinPoint: 
	 * @return: java.lang.reflect.Method
	 **/
	private Method common(JoinPoint joinPoint){
		Signature signature = joinPoint.getSignature();
		MethodSignature methodSignature = (MethodSignature) signature;
		Method method = methodSignature.getMethod();
		return method;
	}

	@Around("webLog()")
	public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
		//记录请求信息
		ReqRspLog webLog = new ReqRspLog();
		webLog.setStartTime(DateUtil.getNowTime());
		//获取当前请求对象
		ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();

		HttpServletRequest request = attributes.getRequest();
		
		Object result = joinPoint.proceed();
		Method method = common(joinPoint);
		String serviceName = "mini-service";
		if (method.isAnnotationPresent(SysLog.class)) {
			SysLog annotation = method.getAnnotation(SysLog.class);
			webLog.setDescription(annotation.value());
			webLog.setVersion(annotation.version());
			serviceName = annotation.service();
		}
		PackingUtil.packingReqRspLog(request, result, method, joinPoint.getArgs(),webLog);

		//	LOGGER.info("{}", JSONUtil.parse(webLog))
		Map<String,Object> logMap = new HashMap<>(5);
		logMap.put("url",webLog.getUrl());
		logMap.put("method",webLog.getMethod());
		logMap.put("parameter",webLog.getParameter());
		logMap.put("spendTime",DateUtil.getNowTime() - webLog.getStartTime());
		logMap.put("description",webLog.getDescription());
		logMap.put("creatTime", webLog.getStartTime());

		/**
		 * Query query = new Query(Criteria.where("username").is(manager.getUsername()))
		 * Update update= new Update()
		 * update.set("username", manager.getUsername());update.set("password",manager.getPassword())
		 * update.set("power", manager.getPower() 
		 * mongoTemplate.updateFirst(query,update,Manager.class)
		 */
		mongoTemplate.insert(webLog, serviceName);
		log.info("打印请求日志:logMap-->[{}],webLog-->[{}]",Markers.appendEntries(logMap), Markers.appendFields(webLog));
		return result;
	}
}
